﻿using System;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Net;

namespace AssCal
{
    public class AssConfig
    {
        public const string AssCal_DataDIR = "asscal/";
        public const string AssCal_CodeDIR = "asscal/code/";

        public const string AssInfo_XML  = AssCal_DataDIR + "assinfo.xml";
        public const string Calendar_CSS = AssCal_CodeDIR + "calendar.css";
        public const string Calendar_JS  = AssCal_CodeDIR + "calendar.js";
        public const string AssCal_CSS   = AssCal_CodeDIR + "asscal.css";
        public const string AssCal_JS    = AssCal_CodeDIR + "asscal.js";
    }

    public class AssUtil
    {
        public static string StrNbrAdd( string nbr1, string nbr2)
        { 
            float i=0, j=0;
            float.TryParse(nbr1, out i);
            float.TryParse(nbr2, out j);
            float ret = i + j;
            return "" + ret;
        }

        protected static char[] Seperators = { ' ', ',', '，' };
        public static string[] TrySplit(string text)
        {
            foreach ( char sep in Seperators)
            {
                string[] parts = text.Split( sep );
                if (parts.Length > 1) return parts;
            }
            string[] rst = { text };
            return rst;
        }

        public static string FirstPart(string text, char sep)
        {
            if (text == null) return "";
            string[] parts = text.Split(sep);
            if (parts.Length >= 1)
            {
                return parts[0];
            }
            return "";
        }

        public static string LastPart(string text, char sep)
        {
            if (text == null) return "";
            string[] parts = text.Split(sep);
            if (parts.Length >= 1)
            {
                return parts[parts.Length-1];
            }
            return "";
        }

        public static Collection<XmlNode> SelectNodes(XmlNodeList xnl, string xpath)
        {
            Collection<XmlNode> ret = new Collection<XmlNode>();
            int sepPos = xpath.IndexOf('/');
            if (sepPos < 0)
            {
                foreach (XmlNode xn in xnl)
                {
                    if (xn.Name == xpath)
                    {
                        ret.Add(xn);
                    }
                }
            }
            else
            {
                string tname = xpath.Substring(0, sepPos);
                string nname = xpath.Substring(sepPos + 1);
                foreach (XmlNode xn in xnl)
                {
                    if (xn.Name == tname)
                    {
                        foreach (XmlNode xn1 in SelectNodes(xn.ChildNodes, nname))
                        {
                            ret.Add(xn1);
                        }
                    }
                }
            }
            return ret;
        }


    }



    public class Represent
    {
        protected string repsented = null;
        protected int number = 0;
        protected PDTYPE type = PDTYPE.PERIOD;

        public enum PDTYPE { TO_AGE, PERIOD };

        public string str()
        {
            if (this.repsented == null)
            {
                return "";
            }
            else
            {
                return this.repsented;
            }
        }

        public int nbr()
        {
            return this.number;
        }

        public string strnbr()
        {
            return ""+this.number;
        }

        public PDTYPE valType()
        {
            return this.type;
        }

        public Represent(string val, PDTYPE tp)
        {
            int.TryParse(val, out this.number);
            this.type = tp;
        }

        public Represent( string rep ) 
        {
            this.repsented = rep;
        }
    }

    public class RAssPeriod : Represent
    {
        public RAssPeriod(string val, PDTYPE tp)
            : base(val, tp)
        {
            this.repsented = this.format(tp);
        }

        public RAssPeriod(string rep)
            : base(rep)
        {
            string[] parts = this.repsented.Split(' ');
            if (parts.Length > 1)
            {
                if (parts[0] == "终")
                {
                    this.number = 0;
                }
                else
                {
                    int.TryParse(parts[0], out this.number);
                }
                if (parts[1] == "年")
                {
                    this.type = PDTYPE.PERIOD;
                }
                else if (parts[1] == "周岁")
                {
                    this.type = PDTYPE.TO_AGE;
                }
            }
        }

        public string format(PDTYPE tp)
        {
            string ret = null;

            if (this.number == 0)
            {
                ret = "终 身";
            }
            else if ( tp == PDTYPE.PERIOD)
            {
                ret = "" + this.number + " 年";
            }
            else if (tp == PDTYPE.TO_AGE)
            {
                ret = "" + this.number + " 周岁";
            }
            else
            {
                ret = null;
            }
            return ret;
        }
    }

    public class RFeePeriod : Represent
    {
        public RFeePeriod(string val, PDTYPE tp)
            : base(val, tp)
        {
            this.repsented = this.format(tp);
        }

        public RFeePeriod(string rep)
            : base(rep)
        {
            string[] parts = this.repsented.Split(' ');
            if (parts.Length > 1)
            {
                if (parts[0] == "缴至")
                {
                    this.type = PDTYPE.TO_AGE;
                    int.TryParse(parts[1], out this.number);
                }
                else
                {
                    this.type = PDTYPE.PERIOD;
                    if (parts[0] == "趸")
                    {
                        this.number = 1;
                    }
                    else
                    {
                        int.TryParse(parts[0], out this.number);
                    }
                }
            }
        }

        public string format(PDTYPE tp)
        {
            string ret = null;

            if (tp == PDTYPE.PERIOD)
            {
                if (this.number == 1)
                {
                    ret = "趸 缴"; //一年缴
                }
                else
                {
                    ret = "" + this.number + " 年缴";
                }
            }
            else if (tp == PDTYPE.TO_AGE)
            {
                ret = "缴至 " + this.number + " 周岁";
            }
            else
            {
                ret = null;
            }
            return ret;
        }
    }

    public class FeeTableRow
    {
        protected string name = null;
        protected Collection<string> values = new Collection<string>();

        public FeeTableRow(XmlNode row)
        {
            if (row.ChildNodes.Count <= 0) return;
            foreach (XmlNode cell in row.ChildNodes)
            {
                XmlAttribute mergeAttrib = cell.Attributes["ss:MergeAcross"];
                if (mergeAttrib != null)
                {
                    int cnt = 1;
                    int.TryParse(mergeAttrib.Value, out cnt);
                    for (int i = 0; i < cnt + 1; i++)
                    {
                        values.Add(cell.InnerText);
                    }
                }
                else
                {
                    values.Add(cell.InnerText);
                }
            }

            if (this.values.Count >= 1)
            {
                this.name = this.values[0];
                this.values.RemoveAt(0);
            }
        }

        public bool isNamed( string text )
        {
            return ( this.name == text );
        }

        public Collection<string> getValues()
        {
            return this.values;
        }

        public Collection<string> getGroupedValues()
        {
            Collection<string> ret = new Collection<string>();
            foreach (string str in this.values)
            {
                if ( string.IsNullOrEmpty(str) ) continue;
                if (ret.IndexOf(str) < 0)
                {
                    ret.Add(str);
                }
            }
            return ret;
        }

        public string getValue(int pos)
        {
            if (pos >= this.values.Count) return "";
            return this.values[pos];
        }

        public Collection<int> getMatchedPos( string val, Collection<int> choices)
        {
            Collection<int> ret = new Collection<int>();
            if (choices == null) return ret;
            foreach (int pos in choices)
            { 
                if ( pos >= this.values.Count ) return ret;
                if (this.values[pos] == val)
                {
                    ret.Add(pos);
                }
            }
            return ret;
        }
    }

    public class FeeTable
    {
        protected const string FeePeriodName = "缴费年限";
        protected const string FeeToAgeName  = "缴至年龄";
        protected const string AssPeriodName = "保障年限";
        protected const string AssToAgeName  = "保至年龄";
        protected const string GenderName    = "性别";
        protected const string FeeUnitName   = "费率单位";

        protected Collection<FeeTableRow> feeTblRows = new Collection<FeeTableRow>();
        protected int maxCols = 0;

        public FeeTable(string fileName)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(fileName);

            Collection<XmlNode> rows = AssUtil.SelectNodes(xmldoc.ChildNodes, "Workbook/Worksheet/Table/Row");
            foreach (XmlNode row in rows)
            {
                FeeTableRow fi = new FeeTableRow(row);
                this.feeTblRows.Add(fi);
                if (fi.getValues().Count > this.maxCols) this.maxCols = fi.getValues().Count;
            }
        }

        protected FeeTableRow locateRowByName(string name)
        {
            foreach (FeeTableRow ftr in this.feeTblRows)
            { 
                if ( ftr.isNamed( name ) ) return ftr;
            }
            return null;
        }

        public bool Query(string gender, string age, RAssPeriod assPriod, RFeePeriod feePeriod, out float feeRate, out float feeUnit)
        {
            feeRate = 0;
            feeUnit = 0;
            if (string.IsNullOrEmpty(gender) || string.IsNullOrEmpty(age)) return false;
            if (this.feeTblRows.Count < 4) return false;

            Collection<int> avaPosCol = new Collection<int>();
            for (int pos = 0; pos < this.maxCols; pos++) avaPosCol.Add(pos);

            FeeTableRow row = null, row1 = null;

            //Check user gender
            if ((row = this.locateRowByName(GenderName)) != null)
            {
                avaPosCol = row.getMatchedPos(gender, avaPosCol);
            }
            else return false;

            //Check ass period/age
            string checkName = null;
            if (assPriod.valType() == Represent.PDTYPE.PERIOD)
            {
                checkName = AssPeriodName;
            }
            else if (assPriod.valType() == Represent.PDTYPE.TO_AGE)
            {
                checkName = AssToAgeName;
            }
            else return false;
            if ((row = this.locateRowByName(checkName)) != null)
            {
                avaPosCol = row.getMatchedPos(""+assPriod.nbr(), avaPosCol);
            }
            else return false;

            //Check fee period/age
            checkName = null;
            if (feePeriod.valType() == Represent.PDTYPE.PERIOD)
            {
                checkName = FeePeriodName;
            }
            else if (feePeriod.valType() == Represent.PDTYPE.TO_AGE)
            {
                checkName = FeeToAgeName;
            }
            else return false;
            if ((row = this.locateRowByName(checkName)) != null)
            {
                avaPosCol = row.getMatchedPos(""+feePeriod.nbr(), avaPosCol);
            }
            else return false;

            //Check user Age
            if (avaPosCol.Count <= 0) return false;
            if ((row = this.locateRowByName(age)) != null && (row1 = this.locateRowByName(FeeUnitName)) != null)
            {
                float.TryParse(row.getValue(avaPosCol[0]), out feeRate);
                float.TryParse(row1.getValue(avaPosCol[0]), out feeUnit);
                return true;
            }
            else return false;
        }

        public Collection<RAssPeriod> getAssPeriods()
        {
            FeeTableRow row = null;
            Collection<RAssPeriod> ret = new Collection<RAssPeriod>();

            if ((row = this.locateRowByName(AssPeriodName)) != null)
            {
                foreach (string str in row.getGroupedValues())
                {
                    RAssPeriod rasp = new RAssPeriod(str, Represent.PDTYPE.PERIOD);
                    ret.Add(rasp);
                }
            }

            if ((row = this.locateRowByName(AssToAgeName)) != null)
            {
                foreach (string str in row.getGroupedValues())
                {
                    RAssPeriod rasp = new RAssPeriod(str, Represent.PDTYPE.TO_AGE);
                    ret.Add(rasp);
                }
            }

            return ret;
        }

        public Collection<RFeePeriod> getFeePeriods()
        {
            FeeTableRow row = null;
            Collection<RFeePeriod> ret = new Collection<RFeePeriod>();

            if ((row = this.locateRowByName(FeePeriodName)) != null)
            {
                foreach (string str in row.getGroupedValues())
                {
                    RFeePeriod rasp = new RFeePeriod(str, Represent.PDTYPE.PERIOD);
                    ret.Add(rasp);
                }
            }

            if ((row = this.locateRowByName(FeeToAgeName)) != null)
            {
                foreach (string str in row.getGroupedValues())
                {
                    RFeePeriod rasp = new RFeePeriod(str, Represent.PDTYPE.TO_AGE);
                    ret.Add(rasp);
                }
            }

            return ret;
        }
    }

    public class AssInfo
    {
        public string name = ""; //保险名称
        public string clas = ""; //保险险种
        public string type = ""; //保险类型
        public string company = ""; //所属公司
        public string sellarea = ""; //发行地区
        public string age = ""; //投保年龄
        public string term = ""; //保险责任
        public string period = ""; //保障期间
        public string bonus = ""; //满期给付
        public string feeType = ""; //缴费方式
        public string fee = ""; //费率表  
        public string rule = ""; //免责条款
        public string special = ""; //保险特色
        public string demo = ""; //示例演示
        public string recomend = ""; //推荐指数

        public string[] sell_areas = null;

        protected HttpServerUtility Server;

        private static string Html_Header_0 = "<td bgcolor=\"#cee7ff\"><span style=\"FONT-WEIGHT: 700; FONT-SIZE: 9pt\">";
        private static string Html_Header_1 = "</span></td>";
        private static string Html_Content_0 = "<td><span style=\"FONT-SIZE: 9pt\">";
        private static string Html_Content_1 = "</span></td>";

        private FeeTable ft = null;


        public AssInfo(HttpServerUtility svr, XmlNode row)
        {
            this.Server = svr;
            if (row.ChildNodes.Count >= 15)
            {
                int idx = 0;
                this.clas     = row.ChildNodes[idx++].InnerText; //险种类别
                this.name     = row.ChildNodes[idx++].InnerText; //保险名称
                this.type     = row.ChildNodes[idx++].InnerText; //保险类型
                this.company  = row.ChildNodes[idx++].InnerText; //所属公司
                this.sellarea = row.ChildNodes[idx++].InnerText; //所属公司
                this.age      = row.ChildNodes[idx++].InnerText; //投保年龄
                this.period   = row.ChildNodes[idx++].InnerText; //保障期间
                this.bonus    = row.ChildNodes[idx++].InnerText; //满期给付
                this.feeType  = row.ChildNodes[idx++].InnerText; //缴费方式
                this.fee      = row.ChildNodes[idx++].InnerText; //费率表  
                this.term     = row.ChildNodes[idx++].InnerText; //保险责任
                this.rule     = row.ChildNodes[idx++].InnerText; //免责条款
                this.special  = row.ChildNodes[idx++].InnerText; //保险特色
                this.demo     = row.ChildNodes[idx++].InnerText; //示例演示
                this.recomend = row.ChildNodes[idx++].InnerText; //推荐指数

                //Add Data DIR prefix to fee table name
                if (this.fee != "" && this.fee != null)
                {
                    this.fee = AssConfig.AssCal_DataDIR + this.fee;
                }

                if (this.sellarea != "" && this.sellarea != null)
                {
                    this.sell_areas = AssUtil.TrySplit(this.sellarea);
                }

            }
        }

        public bool isValid()
        {
            if (this.sell_areas == null || string.IsNullOrEmpty(this.company) || string.IsNullOrEmpty(this.type)
                    || string.IsNullOrEmpty(this.name))
            {
                return false;
            }
            return true;
        }

        public string html( bool isHeader )
        { 
            string ret = "<tr>";
            if (isHeader)
            {
                ret += Html_Header_0 + this.name + Html_Header_1;
                ret += Html_Header_0 + this.type + Html_Header_1;
                ret += Html_Header_0 + this.company + Html_Header_1;
                ret += Html_Header_0 + this.age + Html_Header_1;
                //ret += Html_Header_0 + this.term + Html_Header_1;
                ret += Html_Header_0 + this.period + Html_Header_1;
                ret += Html_Header_0 + this.bonus + Html_Header_1;
                //ret += Html_Header_0 + this.fee + Html_Header_1;
                //ret += Html_Header_0 + this.rule + Html_Header_1;
                //ret += Html_Header_0 + this.special + Html_Header_1;
                ret += Html_Header_0 + this.demo + Html_Header_1;
                ret += Html_Header_0 + this.recomend + Html_Header_1;
            }
            else
            {
                ret += Html_Content_0 + this.name + Html_Content_1;
                ret += Html_Content_0 + this.type + Html_Content_1;
                ret += Html_Content_0 + this.company + Html_Content_1;
                ret += Html_Content_0 + this.age + Html_Content_1;
                //ret += Html_Content_0 + this.term + Html_Content_1;
                ret += Html_Content_0 + this.period + Html_Content_1;
                ret += Html_Content_0 + this.bonus + Html_Content_1;
                //ret += Html_Content_0 + this.fee + Html_Content_1;
                //ret += Html_Content_0 + this.rule + Html_Content_1;
                //ret += Html_Content_0 + this.special + Html_Content_1;
                ret += Html_Content_0 + this.demo + Html_Content_1;
                ret += Html_Content_0 + this.recomend + Html_Content_1;
            }
            ret += "</tr>";
            return ret;
        }

        public bool loadFeeTable()
        {
            if (this.fee == "") return false;
            string fileName = Server.MapPath(this.fee);
            this.ft = new FeeTable(fileName);

            //float fee = this.ft.QueryFee("男", "30", "20", "10);
            return true;
        }

        public bool Query(string gender, int age, RAssPeriod assPriod, RFeePeriod feePeriod, out float feeRate, out float feeUnit)
        {
            feeRate = 0;
            feeUnit = 0;
            if (this.ft != null)
            {
                return this.ft.Query(gender, ""+age, assPriod, feePeriod, out feeRate, out feeUnit);
            }
            else
            {
                return false;
            }
        }

        public Collection<string> LoadFeePeriods()
        {
            Collection<string> ret = new Collection<string>();
            if (ft != null)
            {
                foreach ( RFeePeriod rfd in this.ft.getFeePeriods() )
                {
                    ret.Add(rfd.str());
                }
            }
            return ret;
        }

        public Collection<string> LoadAssPeriods()
        {
            Collection<string> ret = new Collection<string>();
            if (ft != null)
            {
                foreach (RAssPeriod rad in this.ft.getAssPeriods())
                {
                    ret.Add(rad.str());
                }
            }
            return ret;
        }

        protected string loadFileContent(string fn)
        {
            //Must be a txt file
            if (fn == null || fn == "") return "";
            int pos = fn.IndexOf(".txt");
            if ( pos >= 0 && pos >= (fn.Length - 5) )
            {
                string fileName = Server.MapPath( AssConfig.AssCal_DataDIR + fn );
                System.IO.StreamReader sr = new System.IO.StreamReader(fileName);
                string content = sr.ReadToEnd();
                sr.Close();
                return content;
            }
            return fn;
        }

        public string loadTerm()
        {
            return this.loadFileContent( this.term);
        }

        public string loadRule()
        {
            return this.loadFileContent(this.rule);
        }

        public string loadSpecial()
        {
            return this.loadFileContent(this.special);
        }
    }

    public class AssControl
    {
        public System.Web.UI.HtmlControls.HtmlInputSubmit commitForm;
        public System.Web.UI.HtmlControls.HtmlInputSubmit resetForm;
        public System.Web.UI.WebControls.TextBox asBirth;
        public System.Web.UI.WebControls.DropDownList asArea;
        public System.Web.UI.WebControls.DropDownList asType;
        public System.Web.UI.WebControls.DropDownList asClass;
        public System.Web.UI.WebControls.DropDownList asAmount;
        public System.Web.UI.WebControls.TextBox      asAmountTxt;
        public System.Web.UI.WebControls.DropDownList fePeriod;
        public System.Web.UI.WebControls.DropDownList asGender;
        public System.Web.UI.WebControls.DropDownList asCompany;
        public System.Web.UI.WebControls.DropDownList asName;
        public System.Web.UI.WebControls.DropDownList asPeriod;
        //public System.Web.UI.WebControls.DropDownList asIncome;

        public void clear()
        {
            this.asBirth.Text = "";
            this.asAmountTxt.Text = "";
            this.asArea.Items.Clear();
            this.asType.Items.Clear();
            this.asClass.Items.Clear();
            this.asAmount.Items.Clear();
            this.fePeriod.Items.Clear();
            this.asGender.Items.Clear();
            this.asCompany.Items.Clear();
            this.asName.Items.Clear();
            this.asPeriod.Items.Clear();
            //this.asIncome.Items.Clear();
        }

    }

    public class AssForm
    {
        private Collection<AssInfo> all_infos = null;
        private Collection<AssInfo> selectable_infos = null;
        private AssControl          contrl = null;
        private AssInfo             rstInfo = null;

        public string birth = null;
        public string gender = null;
        public string user_area = null;
        public string ass_company = null;
        public string ass_type = null;
        public string ass_clas = null;
        public string ass_name = null;
        public string buy_amount = null;

        public RAssPeriod assPeriod = null;
        public RFeePeriod feePeriod = null;

        protected string ass_period = null;
        protected string fee_period = null;
        //public string income = null;

        protected static string DefaultItem = "---请选择---";
        protected static string DefaultInputItem = "---输入金额---";
        protected static string CustomItem = "自定义";
        protected static string[] AllGenders = { DefaultItem, "男", "女" };
        protected static string[] AllAssAmount = { DefaultInputItem, "50000", "100000", "150000", "200000", "250000", "300000", "350000", "400000", "450000", "500000", "1000000" }; 

        protected string resetForm = null;
        protected string addResult = null;


        public AssForm( NameValueCollection Params, AssControl contrl, Collection<AssInfo> infos )
        {
            this.all_infos = infos;
            this.contrl = contrl;

            this.birth = Params["asBirth"];
            this.gender = Params["asGender"];
            //this.income = Params["asIncome"];
            this.buy_amount = Params["asAmountTxt"];

            this.resetForm = Params["resetForm"];
            this.addResult = Params["addAss"];
            
            if ( this.isResetingForm() )
            {
                this.ass_company = DefaultItem;
                this.ass_clas = DefaultItem;
                this.ass_type = DefaultItem;
                this.ass_name = DefaultItem;
                this.ass_period = DefaultItem;
                this.fee_period = DefaultItem;
                this.user_area = DefaultItem;
            }
            else
            {
                this.ass_company = Params["asCompany"];
                this.ass_clas = Params["asClass"];
                this.ass_type = Params["asType"];
                this.ass_name = Params["asName"];
                this.ass_period = Params["asPeriod"];
                this.fee_period = Params["fePeriod"];
                this.user_area = Params["asArea"];
            }
        }

        public bool isAddingResult()
        {
            return (this.addResult != null);        
        }

        public bool isResetingForm()
        {
            return (this.resetForm != null);
        }

        public void forceResetForm()
        {
            this.resetForm = "force";
            this.ass_company = DefaultItem;
            this.ass_type = DefaultItem;
            this.ass_clas = DefaultItem;
            this.ass_name = DefaultItem;
            this.ass_period = DefaultItem;
            this.fee_period = DefaultItem;
            //this.user_area = DefaultItem;

            this.refreshForm();
        }


        public void refreshForm()
        {
            //Check selectable items
            this.selectable_infos = new Collection<AssInfo>();
            foreach (AssInfo ai in this.all_infos)
            {
                if (this.ass_name != null && this.ass_name != DefaultItem && this.ass_name != ai.name) continue;
                if (this.ass_type != null && this.ass_type != DefaultItem && this.ass_type != ai.type) continue;
                if (this.ass_clas != null && this.ass_clas != DefaultItem && this.ass_clas != ai.clas) continue;
                if (this.ass_company != null && this.ass_company != DefaultItem && this.ass_company != ai.company) continue;
                if (this.user_area != null && this.user_area != DefaultItem && ai.sellarea.IndexOf(this.user_area) < 0) continue;

                this.selectable_infos.Add(ai);
            }

            //Build new form
            this.contrl.clear();

            if (this.birth != null) this.contrl.asBirth.Text = this.birth;

            foreach (string gd in AllGenders) addDropDownItem(this.contrl.asGender, gd);
            if (this.gender != null) setSelectedTrim(this.contrl.asGender, this.gender);

            foreach (string aaa in AllAssAmount) addDropDownItem(this.contrl.asAmount, aaa);
            if (this.buy_amount != null)
            {
                this.contrl.asAmountTxt.Text = this.buy_amount;
                this.buy_amount = setSelectedTrim(this.contrl.asAmount, this.buy_amount);
            }
            else
            { 
                //Set text box to asAmount
                this.contrl.asAmountTxt.Text = this.contrl.asAmount.SelectedItem.Text;
            }

            //foreach (string ai in AllIncome) addDropDownItem(this.contrl.asIncome, ai);
            //if (this.income != null) setSelected(this.contrl.asIncome, this.income);

            addDropDownItem(this.contrl.asCompany, DefaultItem);
            addDropDownItem(this.contrl.asClass, DefaultItem);
            addDropDownItem(this.contrl.asType, DefaultItem);
            addDropDownItem(this.contrl.asName, DefaultItem);
            addDropDownItem(this.contrl.asArea, DefaultItem);

            foreach (AssInfo ai in this.selectable_infos)
            {
                if (!ai.isValid()) continue;

                addDropDownItem(this.contrl.asCompany, ai.company);
                addDropDownItem(this.contrl.asClass, ai.clas);
                addDropDownItem(this.contrl.asType, ai.type);

                foreach (string area in ai.sell_areas)
                {
                    addDropDownItem(this.contrl.asArea, area);
                }
            }
            if (this.ass_company != null) this.ass_company = setSelectedTrim(this.contrl.asCompany, this.ass_company);
            if (this.ass_type != null) this.ass_type = setSelectedTrim(this.contrl.asType, this.ass_type);
            if (this.ass_clas != null) this.ass_clas = setSelectedTrim(this.contrl.asClass, this.ass_clas);
            if (this.user_area != null) this.user_area = setSelectedTrim(this.contrl.asArea, this.user_area);

            foreach (AssInfo ai in this.selectable_infos)
            {
                if (!ai.isValid()) continue;
                if (this.isUserChoosedCompanyEtc())
                {
                    addDropDownItem(this.contrl.asName, ai.name);
                }
            }
            if (this.ass_name != null) this.ass_name = setSelectedTrim(this.contrl.asName, this.ass_name);

            addDropDownItem(this.contrl.fePeriod, DefaultItem);
            addDropDownItem(this.contrl.asPeriod, DefaultItem);
            if (this.selectable_infos.Count == 1)
            { 
                //Selected finished, retrieve the fee period selection for current selection
                this.rstInfo = this.selectable_infos[0];

                this.rstInfo.loadFeeTable();

                foreach (string str in this.rstInfo.LoadFeePeriods())
                {
                    addDropDownItem(this.contrl.fePeriod, str);
                }
                foreach (string str in this.rstInfo.LoadAssPeriods())
                {
                    addDropDownItem(this.contrl.asPeriod, str);
                }
            }
            if (this.fee_period != null)
            {
                this.fee_period = setSelectedTrim(this.contrl.fePeriod, this.fee_period);
                if (this.fee_period != DefaultItem) this.feePeriod = new RFeePeriod(this.fee_period);
            }
            if (this.ass_period != null)
            {
                this.ass_period = setSelectedTrim(this.contrl.asPeriod, this.ass_period);
                if (this.ass_period != DefaultItem) this.assPeriod = new RAssPeriod(this.ass_period);
            }
        }

        protected bool isUserChoosedCompanyEtc()
        {
            if (string.IsNullOrEmpty(this.ass_company) || this.ass_company == DefaultItem) return false;
            if (string.IsNullOrEmpty(this.ass_type) || this.ass_type == DefaultItem) return false;
            if (string.IsNullOrEmpty(this.ass_clas) || this.ass_clas == DefaultItem) return false;
            return true;
        }

        public AssInfo getSelectedAssInfo()
        {
            if (this.ass_name == null || this.ass_name == DefaultItem || this.selectable_infos.Count != 1)
            {
                return null;
            }
            return this.selectable_infos[0];
        }

        public AssInfo getAssInfoByName( string name )
        {
            if (this.all_infos == null) return null;
            foreach (AssInfo info in this.all_infos)
            {
                if (info.name == name)
                {
                    return info;
                }
            }
            return null;
        }

        public bool isReadyToCal()
        {
            if (this.rstInfo != null
                && this.birth != null && this.birth != ""
                && this.buy_amount != null && this.buy_amount != DefaultItem
                && this.gender != null && this.gender != DefaultItem
                && this.user_area != null && this.user_area != DefaultItem
                && this.feePeriod != null && this.assPeriod != null)
            {
                return true;
            }
            return false;
        }

        private static void addDropDownItem(DropDownList list, string name)
        {
            ListItem li = new ListItem();
            li.Text = name;
            li.Value = name;
            if (list.Items.IndexOf(li) < 0)
            {
                list.Items.Add(li);
            }
        }

        private static void setSelected(DropDownList list, string name)
        {
            if (name == null) name = DefaultItem;
            ListItem li = new ListItem();
            li.Text = name;
            li.Value = name;

            int idx = list.Items.IndexOf(li);
            if (idx >= 0)
            {
                list.SelectedIndex = idx;
            }
        }

        private static string setSelectedTrim(DropDownList list, string name)
        {
            setSelected( list, name );

            if (list.Items.Count == 2 && list.Items[0].Value == DefaultItem)
            {
                list.Items.Remove(DefaultItem);
                list.SelectedIndex = 0;
                return list.SelectedItem.Value;
            }
            return name;
        }

    }

    public class AssResult
    {
        protected const string DefaultNumber = "?";
        protected const string PRESSED = "pressed";

        protected const string PX_Name = "ListAssName_";
        protected const string PX_BuyAmount = "ListAssBuyAmount_";
        protected const string PX_FPY = "ListAssFPY_";
        protected const string PX_FeeYears = "ListAssYearCount_";
        protected const string PX_FeeTotal = "ListAssFeeTotal_";
        protected const string PX_Period = "ListAssPeriod_";
        protected const string PX_Age = "ListAssToAge_";
        protected const string PX_View = "ListAssView_";
        protected const string PX_Del = "ListAssDel_";

        private bool isValid = false;
        public bool IsValid
        {
            get { return isValid; }
            set { isValid = value; }
        }

        private int itmIdx = 0;
        public int ItmIdx
        {
            get { return itmIdx; }
            set { itmIdx = value; }
        }

        protected bool isFormated = false;
        protected bool isCaculated = false;

        protected AssInfo assInfo;
        protected AssForm assForm;

        protected string name = null;
        protected string buyAmount = null;

        protected float rst_FeePerYear = 0;
        protected int   rst_FeeYearCount = 0;
        protected int   rst_AssYearCount = 0;
        protected int   rst_FeeAge = 0;
        protected int   rst_AssAge = 0;
        protected int   rst_UserAge = 0;

        protected string feePerYear = null;
        protected string feeYearCount = null;
        protected string assYearCount = null;
        protected string feeAge = null;
        protected string assAge = null;
        //protected string userAge = null;
        protected string totalFee = null;

        //protected int int_FeePerYear = 0;
        //protected int int_FeeYearCount = 0;
        //protected int int_AssYearCount = 0;
        //protected int int_AssAge = 0;
        //protected int int_UserAge = 0;

        protected string btnView = null;
        protected string btnDel = null;

        protected string warn_Message = "";

        public AssResult(AssForm fm)
        {
            this.IsValid = false;
            this.isFormated = false;
            this.isCaculated = true;

            this.assForm = fm;
            if (this.assForm == null) return;
            this.assInfo = this.assForm.getSelectedAssInfo();
            if (this.assInfo == null) return;
            if (!this.assForm.isReadyToCal()) return;

            this.warn_Message = "";

            if (!this.GetUserAge()) return ;

            if (!this.GetUserFee()) return ;

            if (!this.GetAssFeePeriod()) return ;

            if ( this.rst_FeePerYear <= 0)
            {
                this.rst_FeePerYear = 0;
                this.rst_FeeYearCount = 0;
                this.rst_AssYearCount = 0;
                this.rst_AssAge = 0;
                this.rst_UserAge = 0;
                return ;
            }

            this.IsValid = true;
        }

        private bool GetUserAge()
        {
            //计算用户年龄

            this.rst_UserAge = 0;
            int birYear = 0, birMonth = 0, birDay = 0;
            string[] parts = this.assForm.birth.Split('-');
            if (parts.Length == 3)
            {
                int.TryParse(parts[0], out birYear);
                int.TryParse(parts[1], out birMonth);
                int.TryParse(parts[2], out birDay);
            }
            this.rst_UserAge = DateTime.Now.Year - birYear - 1;
            if (DateTime.Now.Month > birMonth)
            {
                this.rst_UserAge++;
            }
            else if (DateTime.Now.Month == birMonth)
            {
                if (DateTime.Now.Day > birDay)
                {
                    this.rst_UserAge++;
                }
            }
            if (this.rst_UserAge > 150 || this.rst_UserAge < 0)
            {
                this.warn_Message = "年龄“" + this.rst_UserAge + "岁”不合规范";
                return false;
            }

            return true;
        }

        private bool GetUserFee()
        {
            //计算用户费率
            float feeRate = 0, feeUnit = 0;
            if ( ! this.assInfo.Query( this.assForm.gender, this.rst_UserAge, this.assForm.assPeriod, this.assForm.feePeriod, out feeRate, out feeUnit) )
            {
                this.warn_Message = "无此保费信息，请检查您的年龄及缴费方式是否符合投保要求。<br>"
                                  + "该保险可投保年龄为：" + this.assInfo.age + "， 缴费方式为：" + this.assInfo.feeType;
                return false;
            }

            int buyAmountInt = 0;
            int.TryParse(AssUtil.FirstPart(this.assForm.buy_amount, ' '), out buyAmountInt);
            if (AssUtil.LastPart(this.assForm.buy_amount, ' ') == "万")
            {
                buyAmountInt = buyAmountInt * 10000;
            }
            int oneShare = (int)feeUnit;
            if (oneShare <= 0)
            {
                this.warn_Message = "请检查费率表中“费率单位”的定义";
                return false;
            }
            if (buyAmountInt % oneShare != 0 )
            {
                this.warn_Message = "输入保险金额需是 "+oneShare+" 的整数倍";
                return false;
            }
            int multiple = buyAmountInt / oneShare;
            this.rst_FeePerYear = feeRate * multiple;
            return true;
        }

        private bool GetAssFeePeriod()
        {
            //计算缴费年限
            if (this.assForm.feePeriod.valType() == Represent.PDTYPE.PERIOD)
            {
                this.rst_FeeYearCount = this.assForm.feePeriod.nbr();
                this.rst_FeeAge = this.rst_UserAge + this.rst_FeeYearCount;
            }
            else if (this.assForm.feePeriod.valType() == Represent.PDTYPE.TO_AGE)
            {
                this.rst_FeeAge = this.assForm.feePeriod.nbr();
                this.rst_FeeYearCount = this.rst_FeeAge - this.rst_UserAge;
            }
            else return false;

            //计算保障年限
            if (this.assForm.assPeriod.nbr() == 0)
            {
                this.rst_AssAge = 0;
                this.rst_AssYearCount = 0;
            }
            else if (this.assForm.assPeriod.valType() == Represent.PDTYPE.PERIOD)
            {
                this.rst_AssYearCount = this.assForm.assPeriod.nbr();
                this.rst_AssAge = this.rst_UserAge + this.rst_AssYearCount;
            }
            else if (this.assForm.assPeriod.valType() == Represent.PDTYPE.TO_AGE)
            {
                this.rst_AssAge = this.assForm.assPeriod.nbr();
                this.rst_AssYearCount = this.rst_AssAge - this.rst_UserAge;
            }
            else return false;
            return true;
        }

        public string GetTerm()
        {
            if (this.assInfo != null)
            {
                return this.assInfo.loadTerm();
            }
            return "";
        }

        public string GetRule()
        {
            if (this.assInfo != null)
            {
                return this.assInfo.loadRule();
            }
            return "";
        }

        public string GetSpecial()
        {
            if (this.assInfo != null)
            {
                return this.assInfo.loadSpecial();
            }
            return "";
        }

        public string PrintWarnHtml()
        {
            if ( this.warn_Message != null && this.warn_Message != "" )
            {
                return "<p><span class=\"WARNING\">" + this.warn_Message + "</span></p>";
            }
            return "";
        }

        protected void formatResult()
        {
            if (!this.IsValid) return;
            if (this.isFormated) return;

            //this.name = "";
            if (this.assInfo != null)
            {
                this.name = this.assInfo.name;
            }

            //this.buyAmount = "";
            if (this.assForm != null)
            {
                this.buyAmount = this.assForm.buy_amount;
            }
            string[] parts = this.buyAmount.Split(' ');
            if (parts.Length >= 2)
            {
                if (parts[1] == "万")
                {
                    this.buyAmount = parts[0] + "0000";
                }
            }
            this.buyAmount += " 元";

            this.feePerYear = "" + this.rst_FeePerYear.ToString("#.##") + " 元";
            this.totalFee = "" + ((float)(this.rst_FeePerYear * this.rst_FeeYearCount)).ToString("#.##") + " 元";
            this.feeYearCount = (new RFeePeriod("" + this.rst_FeeYearCount, Represent.PDTYPE.PERIOD)).str();
            this.assYearCount = (new RAssPeriod("" + this.rst_AssYearCount, Represent.PDTYPE.PERIOD)).str();

            this.feeAge = (new RFeePeriod("" + this.rst_FeeAge, Represent.PDTYPE.TO_AGE)).str();
            this.assAge = (new RAssPeriod("" + this.rst_AssAge, Represent.PDTYPE.TO_AGE)).str();

            this.isFormated = true;
        }

        public string PrintResultHtml()
        {
            if (!this.IsValid) return "";
            if (this.isByCaculated()) this.formatResult();

            string rst = "";
            rst += "<span class=\"Normal\">年交保费：</span>\n";
            rst += "<span class=\"AssAmount\">" + this.feePerYear + "</span>\n";
            rst += "<span class=\"Normal\">；</span>\n";
            rst += "<span class=\"Normal\">交费期间：</span>\n";
            rst += "<span class=\"AssAmount\">" + this.feeYearCount + "</span>\n";
            rst += "<span cass=\"Normal\">；</span>\n";
            rst += "<span class=\"Normal\">保险期间：</span>\n";
            rst += "<span class=\"AssAmount\">" + this.assYearCount + "</span>\n";
            rst += "<span class=\"Normal\">；</span>\n";
            rst += "<span class=\"Normal\">或至</span>\n";
            rst += "<span class=\"AssAmount\"><b><font color=\"#FF0000\">" + this.assAge + "</font></b></span>\n";

            return rst;
        }

        protected string newLineHtml(string nm, string id, int size, bool isNbr)
        {
            string ipt_class = null ;
            if (isNbr)
            {
                ipt_class = "ipt_dsp_nbr";
            }
            else
            {
                ipt_class = "ipt_dsp_txt";
            }

            string rst = "<td class=\"td_" + (this.ItmIdx % 2) 
                + "\"><input type=\"text\" name=\"" + id 
                + "\" class=\"" + ipt_class 
                + "\" value=\"" + nm 
                + "\" size=\"" + size 
                + "\"/></td>\n";
            return rst;
        }

        public string PrintRowHtml()
        {
            if (!this.IsValid) return "";
            if (this.isByCaculated()) this.formatResult();

            string rst = "";
            rst += "<tr>\n";
            rst += this.newLineHtml( this.name,         PX_Name + this.itmIdx,      22, false);
            rst += this.newLineHtml( this.buyAmount,    PX_BuyAmount + this.itmIdx, 10,  true);
            rst += this.newLineHtml( this.feePerYear,   PX_FPY + this.itmIdx,       10,  true);
            rst += this.newLineHtml( this.feeYearCount, PX_FeeYears + this.itmIdx,  6,  true);
            rst += this.newLineHtml( this.totalFee,     PX_FeeTotal + this.itmIdx,  10,  true);
            rst += this.newLineHtml( this.assYearCount, PX_Period + this.itmIdx,    6,  true);
            rst += this.newLineHtml( this.assAge,       PX_Age + this.itmIdx,       6,  true);

            rst += "<td align=\"center\" class=\"td_" + (this.ItmIdx % 2)  + "\">\n";
            rst += "<input type=\"button\" name=\"" + PX_View + this.itmIdx + "\" value=\"查看\" onclick=\"return AssJS.markBtnViewSelected();\" />";
            rst += "<input type=\"button\" name=\"" + PX_Del  + this.itmIdx + "\" value=\"删除\" onclick=\"return AssJS.markBtnDelSelected();\" />";
            //rst += "<button type=\"submit\" name=\"ListAssView_" + this.itmIdx + "\">查看</button>\n";
            //rst += "<button type=\"submit\" name=\"ListAssDel_" + this.itmIdx + "\">删除</button>\n";
            rst += "</td>\n";
            rst += "</tr>\n";
            return rst;
        }

        public AssResult(AssForm fm, NameValueCollection Params, int index)
        {
            this.IsValid = false;
            this.isFormated = true;
            this.isCaculated = false;

            this.itmIdx = index;

            this.assForm = fm;
            if (this.assForm == null) return;

            this.name = Params[PX_Name + index];
            if (this.name == null) return;

            this.buyAmount = Params[PX_BuyAmount + index];
            if (this.buyAmount == null) return;

            this.feePerYear = Params[PX_FPY + index];
            if (this.feePerYear == null) return;

            this.feeYearCount = Params[PX_FeeYears + index];
            if (this.feeYearCount == null) return;

            this.totalFee = Params[PX_FeeTotal + index];
            if (this.totalFee == null) return;

            this.assYearCount = Params[PX_Period + index];
            if (this.assYearCount == null) return;

            this.assAge = Params[PX_Age + index];
            if (this.assAge == null) return;

            this.assInfo = this.assForm.getAssInfoByName( this.name );
            if (this.assInfo == null) return;

            //this.btnView = Params["ListAssView_" + index];
            //this.btnDel = Params["ListAssDel_" + index];

            this.IsValid = true;
        }



        public bool isBtnViewPressed()
        {
            return (this.btnView == PRESSED);
        }

        public bool isBtnDelPressed()
        {
            return (this.btnDel == PRESSED);
        }

        public void checkViewDelPressed( string viewSelected, string delSelected)
        {
            if (viewSelected != null)
            {
                //ListAssView_
                if (viewSelected == ("ListAssView_" + this.itmIdx))
                {
                    this.btnView = PRESSED;
                }
            }

            if (delSelected != null)
            {
                //ListAssDel_
                if (delSelected == ("ListAssDel_" + this.itmIdx))
                {
                    this.btnDel = PRESSED;
                }
            }
        }

        public bool isByCaculated()
        {
            return this.isCaculated;
        }

        public AssResult()
        {
            this.IsValid = false;
            this.isFormated = false;
            this.isCaculated = false;
            this.ItmIdx = -1;

            this.assForm = null;

            this.name = "总计";

            this.buyAmount = "0";
            this.feePerYear = "0";
            this.totalFee = "0";

            this.feeYearCount = "";
            this.assYearCount = "";
            this.assAge = "";

            this.IsValid = true;
        }

        public void addResult(AssResult arst)
        {
            this.buyAmount = AssUtil.StrNbrAdd(this.buyAmount, AssUtil.FirstPart(arst.buyAmount, ' '));
            this.feePerYear = AssUtil.StrNbrAdd(this.feePerYear, AssUtil.FirstPart(arst.feePerYear, ' '));
            this.totalFee = AssUtil.StrNbrAdd(this.totalFee, AssUtil.FirstPart(arst.totalFee, ' '));
        }

        public string PrintSummaryHtml()
        {
            this.buyAmount += " 元";
            this.feePerYear += " 元";
            this.totalFee += " 元";

            string rst = "";
            rst += "<tr>\n";
            rst += "<td class=\"td_sum\">" + this.name + "</td>\n";
            rst += "<td class=\"td_sum\" align=\"right\">" + this.buyAmount + "</td>\n";
            rst += "<td class=\"td_sum\" align=\"right\">" + this.feePerYear + "</td>\n";
            rst += "<td ></td>\n";
            rst += "<td class=\"td_sum\" align=\"right\">" + this.totalFee + "</td>\n";
            rst += "<td ></td>\n";
            rst += "<td ></td>\n";

            rst += "<td ></td>\n";
            rst += "</tr>\n";
            return rst;
        }
    }

    public partial class AssCalPage : System.Web.UI.Page
    {
        private Collection<AssInfo> infos  = new Collection<AssInfo>();
        private AssInfo             header = null;
        private AssForm             main_form = null;
        private AssResult           curr_result = null;
        private Collection<AssResult> all_results = new Collection<AssResult>();
        private AssResult           result_summary = null;

        private const string Html_Table_0 = "<table style=\"BORDER-COLLAPSE: collapse\" cellspacing=\"1\" border=\"1\">";
        private const string Html_Table_1 = "</table>";

        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void setQuery(NameValueCollection Params)
        {
            AssControl contrl = new AssControl();

            contrl.asAmount = asAmount;
            contrl.asAmountTxt = asAmountTxt;
            contrl.asArea = asArea;
            contrl.asBirth = asBirth;
            contrl.asCompany = asCompany;
            contrl.asGender = asGender;
            //contrl.asIncome = asIncome;
            contrl.asName = asName;
            contrl.asPeriod = asPeriod;
            contrl.asType = asType;
            contrl.asClass = asClass;
            contrl.fePeriod = fePeriod;

            this.main_form = new AssForm(Params, contrl, this.infos);
        }

        protected void initAssInfo()
        {
            string fileName = Server.MapPath(AssConfig.AssInfo_XML);
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(fileName);

            Collection<XmlNode> rows = AssUtil.SelectNodes(xmldoc.ChildNodes, "Workbook/Worksheet/Table/Row");
            this.header = new AssInfo(Server, rows[0]);
            rows.RemoveAt(0);
            int i = 0;
            foreach (XmlNode row in rows)
            {
                this.infos.Add(new AssInfo(Server, row));
                //if (i++ > AssConfig.AssCal_DataDIR.Length) break;
            }
        }

        public void handleMain( NameValueCollection Params )
        { 
            this.initAssInfo();
            this.setQuery(Request.Params);

            this.main_form.refreshForm();

            //Hanlde last results
            int idx = 0;
            Collection<AssResult> temp_all_rsts = new Collection<AssResult>();
            while (true)
            {
                AssResult arst = new AssResult(this.main_form, Request.Params, idx++);
                if (!arst.IsValid) break;
                arst.checkViewDelPressed(Params["viewBtnSelect"], Params["delBtnSelect"]);
                temp_all_rsts.Add(arst);
            }

            //Check which is deleted
            idx = 0;
            foreach (AssResult arst in temp_all_rsts)
            {
                if (!arst.isBtnDelPressed())
                {
                    arst.ItmIdx = idx++;
                    this.all_results.Add(arst);
                }
            }

            //Make current result, if possible, push current result to result collection
            this.curr_result = new AssResult(this.main_form);
            if (this.main_form.isAddingResult())
            {
                this.curr_result.ItmIdx = this.all_results.Count;
                this.all_results.Add(this.curr_result);
                this.main_form.forceResetForm();
            }
        }

        public void printAssList()
        {
            foreach ( AssResult result in this.all_results)
            {
                if (result.IsValid)
                {
                    Response.Write(result.PrintRowHtml());
                }
            }

            //Caculate sum result
            this.result_summary = new AssResult();
            foreach (AssResult result in this.all_results)
            {
                if (result.IsValid)
                {
                    this.result_summary.addResult(result);
                }
            }
            if (this.result_summary != null)
            {
                Response.Write( this.result_summary.PrintSummaryHtml() );
            }
        }

        public void printCurrResult()
        {
            if (this.main_form.isAddingResult()) return;
            if (this.curr_result != null)
            {
                Response.Write(this.curr_result.PrintWarnHtml());
                Response.Write( this.curr_result.PrintResultHtml() );
            }
        }

        public string getTerm()
        {
            foreach (AssResult result in this.all_results)
            {
                if (result.isBtnViewPressed())
                {
                    return result.GetTerm();
                }
            }
            return this.curr_result.GetTerm();        
        }

        public string getRule()
        {
            foreach (AssResult result in this.all_results)
            {
                if (result.isBtnViewPressed())
                {
                    return result.GetRule();
                }
            }
            return this.curr_result.GetRule();
        }

        public string getSpecial()
        {
            foreach (AssResult result in this.all_results)
            {
                if (result.isBtnViewPressed())
                {
                    return result.GetSpecial();
                }
            }
            return this.curr_result.GetSpecial();
        }

    }
}
